import junit.framework.TestCase;

public class BlockTest extends TestCase {

	public void testIntervalMainOperations ( ) {
		Block.Interval int1 = new Block.Interval(0, 0);
		assertEquals(0, int1.getLeftEnd());
		assertEquals(0, int1.getRightEnd());
		assertEquals("[ 0, 0 ]", int1.toString());
		// testing increment
		int1 = int1.increment();
		assertEquals(1, int1.getLeftEnd());
		assertEquals(1, int1.getRightEnd());
		assertEquals("[ 1, 1 ]", int1.toString());
		// testing decrement
		int1 = int1.decrement();
		assertEquals(0, int1.getLeftEnd());
		assertEquals(0, int1.getRightEnd());
		assertEquals("[ 0, 0 ]", int1.toString());
		
		int1 = new Block.Interval(3, 4);
		assertEquals(3, int1.getLeftEnd());
		assertEquals(4, int1.getRightEnd());
		assertEquals("[ 3, 4 ]", int1.toString());
		// testing increment
		int1 = int1.increment();
		assertEquals(4, int1.getLeftEnd());
		assertEquals(5, int1.getRightEnd());
		assertEquals("[ 4, 5 ]", int1.toString());
		// testing decrement
		int1 = int1.decrement();
		assertEquals(3, int1.getLeftEnd());
		assertEquals(4, int1.getRightEnd());
		assertEquals("[ 3, 4 ]", int1.toString());
	}
	
	public void testIntervalEquals ( ) {
		Block.Interval int1 = new Block.Interval(2, 3);
		Block.Interval int2 = new Block.Interval(3, 4);
		assertFalse(int1.equals(int2));
		assertFalse(int1.toString().equals(int2.toString()));
		int1 = int1.increment();
		assertTrue(int1.equals(int2));
		assertTrue(int1.toString().equals(int2.toString()));
		int1 = int2.increment();
		int2 = new Block.Interval(4, 5);
		assertTrue(int1.equals(int2));
		assertTrue(int1.toString().equals(int2.toString()));
	}
	
	public void testIntervalIntersectsWith ( ) {
		Block.Interval int1;
		Block.Interval int2;
		
		// two non-intersecting one-element intervals
		// []	
		// 		[]
		int1 = new Block.Interval(0, 0);
		int2 = new Block.Interval(2, 2);
		assertFalse(int1.intersectsWith(int2));
		assertFalse(int2.intersectsWith(int1));
		
		// two non-intersecting one-element intervals with adjacent endpoints
		// [] 
		//   []
		int1 = new Block.Interval(0, 0);
		int2 = new Block.Interval(1, 1);
		assertFalse(int1.intersectsWith(int2));
		assertFalse(int2.intersectsWith(int1));
		
		// two one-element intervals with both endpoints intersecting
		// []
		// []
		int1 = new Block.Interval(1, 1);
		int2 = new Block.Interval(1, 1);
		assertTrue(int1.intersectsWith(int2));
		assertTrue(int2.intersectsWith(int1));
		
		// two many-element intervals intersecting at only one point
		// [    ]
		//      [    ]
		int1 = new Block.Interval(0, 5);
		int2 = new Block.Interval(5, 10);
		assertTrue(int1.intersectsWith(int2));
		assertTrue(int2.intersectsWith(int1));
		
		// two non-intersecting, adjacent intervals
		// [    ] 
		//       [    ]
		int1 = new Block.Interval(0, 4);
		int2 = new Block.Interval(5, 9);
		assertFalse(int1.intersectsWith(int2));
		assertFalse(int2.intersectsWith(int1));
		
		// two non-intersecting, adjacent intervals (one-element)
		// [    ]
		//       []
		int1 = new Block.Interval(0, 4);
		int2 = new Block.Interval(5, 5);
		assertFalse(int1.intersectsWith(int2));
		assertFalse(int2.intersectsWith(int1));
		
		// two non-intersecting, adjacent intervals (one-element)
		// []
		//   [    ]
		int1 = new Block.Interval(0, 0);
		int2 = new Block.Interval(1, 5);
		assertFalse(int1.intersectsWith(int2));
		assertFalse(int2.intersectsWith(int1));
		
		// two overlapping many-element intervals
		// [    ]
		//    [    ]
		int1 = new Block.Interval(0, 5);
		int2 = new Block.Interval(3, 8);
		assertTrue(int1.intersectsWith(int2));
		assertTrue(int2.intersectsWith(int1));
		
		// one many-element interval wrapping another many-element interval, with left endpoints same
		// [    ]
		// [  ]
		int1 = new Block.Interval(0, 5);
		int2 = new Block.Interval(0, 10);
		assertTrue(int1.intersectsWith(int2));
		assertTrue(int2.intersectsWith(int1));
		
		// one many-element interval wrapping another one-element interval, with left endpoints same
		// [    ]
		// []
		int1 = new Block.Interval(0, 0);
		int2 = new Block.Interval(0, 10);
		assertTrue(int1.intersectsWith(int2));
		assertTrue(int2.intersectsWith(int1));
		
		// one many-element interval wrapping another many-element interval, with left endpoints same
		// [    ]
		//   [  ]
		int1 = new Block.Interval(0, 10);
		int2 = new Block.Interval(5, 10);
		assertTrue(int1.intersectsWith(int2));
		assertTrue(int2.intersectsWith(int1));
		
		// one many-element interval wrapping another one-element interval, with right endpoints same
		// [    ]
		//     []
		int1 = new Block.Interval(0, 10);
		int2 = new Block.Interval(10, 10);
		assertTrue(int1.intersectsWith(int2));
		assertTrue(int2.intersectsWith(int1));
		
		// one many-element interval wrapping another many-element interval
		// [       ]
		//    [  ]
		int1 = new Block.Interval(0, 10);
		int2 = new Block.Interval(4, 7);
		assertTrue(int1.intersectsWith(int2));
		assertTrue(int2.intersectsWith(int1));
		
		// one many-element interval wrapping another one-element interval
		// [       ]
		//    []
		int1 = new Block.Interval(0, 10);
		int2 = new Block.Interval(4, 4);
		assertTrue(int1.intersectsWith(int2));
		assertTrue(int2.intersectsWith(int1));
	}
	
	public void testConstructor ( ) {
		Block block = new Block (1, 1, 0, 0);
		assertEquals(1, block.getLength());
		assertEquals(1, block.getWidth());
		assertEquals("Block of length 1 width 1 at (0, 0)", block.toString());
		
		block = new Block (1, 1, 5, 5);
		assertEquals(1, block.getLength());
		assertEquals(1, block.getWidth());
		assertEquals("Block of length 1 width 1 at (5, 5)", block.toString());
		
		block = new Block (5, 6, 0, 0);
		assertEquals(5, block.getLength());
		assertEquals(6, block.getWidth());
		assertEquals("Block of length 5 width 6 at (0, 0)", block.toString());
		
		block = new Block (5, 6, 5, 6);
		assertEquals(5, block.getLength());
		assertEquals(6, block.getWidth());
		assertEquals("Block of length 5 width 6 at (5, 6)", block.toString());
	}
	
	public void testEquals ( ) {
		Block block1 = new Block (1, 1, 0, 0);
		Block block2 = new Block (1, 1, 0, 0);
		assertTrue (block1.equals(block2));
		block2 = new Block (1, 2, 0, 0);
		assertFalse (block1.equals(block2));
		block2 = new Block (2, 1, 0, 0);
		assertFalse (block1.equals(block2));
		block2 = new Block (1, 1, 5, 0);
		assertFalse (block1.equals(block2));
		block2 = new Block (1, 1, 0, 5);
		assertFalse (block1.equals(block2));
	}
	
	public void testIntersectsWith ( ) {
		Block block1 = new Block (1, 1, 0, 0);
		Block block2 = new Block (1, 1, 0, 0);
		assertTrue (block1.intersectsWith (block2));
		assertTrue (block2.intersectsWith (block1));
		// upper left hand corner
		block1 = new Block (2, 2, 0, 0);
		block2 = new Block (2, 2, 0, 2);
		assertFalse (block1.intersectsWith (block2));
		assertFalse (block2.intersectsWith (block1));
		block2 = new Block (2, 2, 2, 0);
		assertFalse (block1.intersectsWith (block2));
		assertFalse (block2.intersectsWith (block1));
		block2 = new Block (2, 2, 2, 2);
		assertFalse (block1.intersectsWith (block2));
		assertFalse (block2.intersectsWith (block1));
		block2 = new Block (2, 2, 1, 0);
		assertTrue (block1.intersectsWith (block2));
		assertTrue (block2.intersectsWith (block1));
		block2 = new Block (2, 2, 1, 1);
		assertTrue (block1.intersectsWith (block2));
		assertTrue (block2.intersectsWith (block1));
		block2 = new Block (2, 2, 0, 1);
		assertTrue (block1.intersectsWith (block2));
		assertTrue (block2.intersectsWith (block1));
		// upper right hand corner
		block1 = new Block (2, 2, 0, 3);
		block2 = new Block (2, 2, 0, 1);
		assertFalse (block1.intersectsWith (block2));
		assertFalse (block2.intersectsWith (block1));
		block2 = new Block (2, 2, 2, 3);
		assertFalse (block1.intersectsWith (block2));
		assertFalse (block2.intersectsWith (block1));
		block2 = new Block (2, 2, 2, 1);
		assertFalse (block1.intersectsWith (block2));
		assertFalse (block2.intersectsWith (block1));
		block2 = new Block (2, 2, 0, 2);
		assertTrue (block1.intersectsWith (block2));
		assertTrue (block2.intersectsWith (block1));
		block2 = new Block (2, 2, 1, 2);
		assertTrue (block1.intersectsWith (block2));
		assertTrue (block2.intersectsWith (block1));
		block2 = new Block (2, 2, 1, 3);
		assertTrue (block1.intersectsWith (block2));
		assertTrue (block2.intersectsWith (block1));
		// lower left hand corner
		block1 = new Block (2, 2, 3, 0);
		block2 = new Block (2, 2, 3, 2);
		assertFalse (block1.intersectsWith (block2));
		assertFalse (block2.intersectsWith (block1));
		block2 = new Block (2, 2, 1, 0);
		assertFalse (block1.intersectsWith (block2));
		assertFalse (block2.intersectsWith (block1));
		block2 = new Block (2, 2, 1, 2);
		assertFalse (block1.intersectsWith (block2));
		assertFalse (block2.intersectsWith (block1));
		block2 = new Block (2, 2, 2, 0);
		assertTrue (block1.intersectsWith (block2));
		assertTrue (block2.intersectsWith (block1));
		block2 = new Block (2, 2, 2, 1);
		assertTrue (block1.intersectsWith (block2));
		assertTrue (block2.intersectsWith (block1));
		block2 = new Block (2, 2, 3, 1);
		assertTrue (block1.intersectsWith (block2));
		assertTrue (block2.intersectsWith (block1));
		// lower right hand corner
		block1 = new Block (2, 2, 3, 3);
		block2 = new Block (2, 2, 3, 1);
		assertFalse (block1.intersectsWith (block2));
		assertFalse (block2.intersectsWith (block1));
		block2 = new Block (2, 2, 1, 3);
		assertFalse (block1.intersectsWith (block2));
		assertFalse (block2.intersectsWith (block1));
		block2 = new Block (2, 2, 1, 1);
		assertFalse (block1.intersectsWith (block2));
		assertFalse (block2.intersectsWith (block1));
		block2 = new Block (2, 2, 3, 2);
		assertTrue (block1.intersectsWith (block2));
		assertTrue (block2.intersectsWith (block1));
		block2 = new Block (2, 2, 2, 2);
		assertTrue (block1.intersectsWith (block2));
		assertTrue (block2.intersectsWith (block1));
		block2 = new Block (2, 2, 2, 3);
		assertTrue (block1.intersectsWith (block2));
		assertTrue (block2.intersectsWith (block1));
		// in middle
		block1 = new Block (1, 1, 2, 2);
		block2 = new Block (1, 3, 1, 1);
		assertFalse (block1.intersectsWith (block2));
		assertFalse (block2.intersectsWith (block1));
		block2 = new Block (1, 3, 3, 1);
		assertFalse (block1.intersectsWith (block2));
		assertFalse (block2.intersectsWith (block1));
		block2 = new Block (3, 1, 1, 1);
		assertFalse (block1.intersectsWith (block2));
		assertFalse (block2.intersectsWith (block1));
		block2 = new Block (3, 1, 1, 3);
		assertFalse (block1.intersectsWith (block2));
		assertFalse (block2.intersectsWith (block1));
		block2 = new Block (3, 1, 1, 2);
		assertTrue (block1.intersectsWith (block2));
		assertTrue (block2.intersectsWith (block1));
		block2 = new Block (1, 3, 2, 1);
		assertTrue (block1.intersectsWith (block2));
		assertTrue (block2.intersectsWith (block1));
	}
	
	public void testMoves ( ) {
		Block block1 = new Block (2, 2, 0, 0);
		assertEquals ("Block of length 2 width 2 at (0, 0)", block1.toString());
		block1 = block1.moveDown (10, 10);
		assertEquals("Block of length 2 width 2 at (1, 0)", block1.toString());
		block1 = block1.moveRight (10, 10);
		assertEquals("Block of length 2 width 2 at (1, 1)", block1.toString());
		block1 = block1.moveRight (10, 10);
		assertEquals("Block of length 2 width 2 at (1, 2)", block1.toString());
		block1 = block1.moveDown (10, 10);
		assertEquals("Block of length 2 width 2 at (2, 2)", block1.toString());
		block1 = block1.moveLeft (10, 10);
		assertEquals("Block of length 2 width 2 at (2, 1)", block1.toString());
		block1 = block1.moveUp (10, 10);
		assertEquals("Block of length 2 width 2 at (1, 1)", block1.toString());
		block1 = block1.moveUp (10, 10);
		assertEquals("Block of length 2 width 2 at (0, 1)", block1.toString());
		block1 = block1.moveLeft (10, 10);
		assertEquals("Block of length 2 width 2 at (0, 0)", block1.toString());
		block1 = block1.moveDown (10, 10);
		assertEquals("Block of length 2 width 2 at (1, 0)", block1.toString());
		block1 = block1.moveDown (10, 10);
		assertEquals("Block of length 2 width 2 at (2, 0)", block1.toString());
	}
}